﻿using DJLang;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
using ZerAx.ObjectNotation;

namespace BlockOS.Client.Res
{
    public class GameResource
    {
        public Texture2D chunkTexture;
        public Dictionary<string, BlockModelDef> modelDefs;
        public Dictionary<string, Func<Vector2, Vector2>> converters;
        public Dictionary<string, Block> blocks;

        private DJEnv env;

        public bool IsDone { get; private set; }

        public GameResource()
        {
            env = new DJEnv();
            env.LoadStandard(DJStdLoadFlags.Minimal);
            env.PutLibrary(typeof(BlockModelLoadLib));
            env.Put("res", new DJRef<GameResource>(this));
        }

        public BlockModel GetBlockModel(string blockName, Dictionary<string, Zon> states)
        {
            if (blocks.TryGetValue(blockName, out var block))
            {
                return block.GetBlockModel(states, converters);
            }
            return null;
        }

        public BlockModel GetBlockModel(BlockData block) => GetBlockModel(block.id, block.metas);

        public IEnumerator Reload(IEnumerable<string> extraPackPaths)
        {
            IsDone = false;
            var loadPacks = Enumerable.Repeat(Path.Combine(Application.streamingAssetsPath, "Default.zip"), 1).Concat(extraPackPaths);

            var packs = new ResLoader();

            foreach (var path in loadPacks)
            {
                yield return packs.LoadPack(path);
            }

            chunkTexture = new Texture2D(0, 0)
            {
                filterMode = FilterMode.Point
            };

            chunkTexture.wrapMode = TextureWrapMode.Clamp;

            var ranges = chunkTexture.PackTextures(packs.combinedPack.textures.Values.ToArray(), 1);

            converters = new Dictionary<string, Func<Vector2, Vector2>>(packs.combinedPack.textures.Keys
                .Zip(ranges, (x, y) => new KeyValuePair<string, Func<Vector2, Vector2>>(x, v => UVConverts.GetChunkUV(y, v))));

            modelDefs = packs.combinedPack.modelDefs;
            blocks = new Dictionary<string, Block>(packs.combinedPack.blocks
                .Select(x =>
                {
                    x.Value.root = env;
                    return new KeyValuePair<string, Block>(x.Key, x.Value);
                }));

            IsDone = true;
        }
    }
}
